package com.haohan.jingyuan.customer.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haohan.jingyuan.common.enums.ErrorEnum;
import com.haohan.jingyuan.common.exception.BusinessException;
import com.haohan.jingyuan.common.util.EntityUtil;
import com.haohan.jingyuan.customer.dao.CustomerFileMapper;
import com.haohan.jingyuan.customer.dao.CustomerGroupMapper;
import com.haohan.jingyuan.customer.dao.CustomerInfoMapper;
import com.haohan.jingyuan.customer.dao.CustomerTagMapper;
import com.haohan.jingyuan.customer.entity.CustomerGroupInfo;
import com.haohan.jingyuan.customer.entity.CustomerTag;
import com.haohan.jingyuan.customer.dto.req.CreateCustomerFileRequest;
import com.haohan.jingyuan.customer.dto.req.DeleteCustomerFileRequest;
import com.haohan.jingyuan.customer.dto.req.QueryCustomerFileListByCustomerIdRequest;
import com.haohan.jingyuan.customer.dto.req.QueryCustomerFileListRequest;
import com.haohan.jingyuan.customer.dto.req.UpdateCustomerFileRequest;
import com.haohan.jingyuan.customer.dto.resp.CustomerFileGroupResp;
import com.haohan.jingyuan.customer.dto.resp.CustomerFileListResp;
import com.haohan.jingyuan.customer.dto.resp.CustomerFileResp;
import com.haohan.jingyuan.customer.dto.resp.CustomerFileTreeResp;
import com.haohan.jingyuan.customer.entity.CustomerFile;
import com.haohan.jingyuan.customer.entity.CustomerInfo;
import com.haohan.jingyuan.customer.helper.CustomerFileRespHelper;
import com.haohan.jingyuan.gateway.holder.UserContextHolder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 客户材料服务实现类
 *
 * @ClassName CustomerFileService
 * @Description 客户材料相关业务逻辑实现
 * @Author hexijun
 * @Time 2025/01/31 10:00
 * @Version 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CustomerFileService {

    /**
     * 客户材料Mapper
     */
    private final CustomerFileMapper customerFileMapper;

    /**
     * 客户信息Mapper
     */
    private final CustomerInfoMapper customerInfoMapper;

    /**
     * 客户分组Mapper
     */
    private final CustomerGroupMapper customerGroupMapper;

    /**
     * 客户标签Mapper
     */
    private final CustomerTagMapper customerTagMapper;

    /**
     * 创建客户材料
     *
     * @param request 创建客户材料请求
     * @return 客户材料信息
     */
    public CustomerFileResp createCustomerFile(CreateCustomerFileRequest request) {
        log.info("CustomerFileServiceImpl.createCustomerFile BEGIN ==> customerId: {}", request.getCustomerId());

        // 验证客户是否存在
        if (customerInfoMapper.findByCustomerId(request.getCustomerId()) == null) {
            throw new BusinessException(ErrorEnum.CUSTOMER_NOT_FOUND);
        }

        // 检查同一个客户ID下是否已存在相同的文件key（只检查未删除的记录，ukid=0）
        CustomerFile existFile = customerFileMapper.findByCustomerIdAndFileKey(request.getCustomerId(), request.getFileKey());
        if (existFile != null) {
            throw new BusinessException(ErrorEnum.DATABASE_ERROR.getCode(), "该客户下已存在相同的文件key");
        }

        // 校验分组是否存在且type=2（客户材料分组）（如果传入了分组）
        if (request.getGroupCode() != null && !request.getGroupCode().trim().isEmpty()) {
            CustomerGroupInfo group = customerGroupMapper.findByGroupIdAndType(request.getGroupCode(), 2);
            if (group == null) {
                throw new BusinessException(ErrorEnum.GROUP_NOT_FOUND);
            }
        }

        // 校验并规范化标签（如果传入了标签）
        String normalizedTag = validateAndNormalizeTag(request.getTag());

        // 创建客户材料
        CustomerFile customerFile = new CustomerFile();
        customerFile.setCustomerId(request.getCustomerId());
        customerFile.setFileKey(request.getFileKey());
        customerFile.setFileName(request.getFileName());
        customerFile.setFileType(request.getFileType());
        customerFile.setSignAt(request.getSignAt());
        customerFile.setExpireAt(request.getExpireAt());
        customerFile.setGroupCode(request.getGroupCode());
        customerFile.setTag(normalizedTag);
        // ukid默认为0
        customerFile.setUkid(0L);
        EntityUtil.setCreateAndModifyInfo(customerFile, UserContextHolder.getCurrentUserName());

        // 保存到数据库
        int result = customerFileMapper.insert(customerFile);
        if (result <= 0) {
            throw new BusinessException(ErrorEnum.DATABASE_ERROR);
        }

        // 查询分组和标签信息
        Map<String, CustomerGroupInfo> groupMap = null;
        Map<String, CustomerTag> tagMap = null;
        if (customerFile.getGroupCode() != null && !customerFile.getGroupCode().trim().isEmpty()) {
            CustomerGroupInfo group = customerGroupMapper.findByGroupIdAndType(customerFile.getGroupCode(), 2);
            if (group != null) {
                groupMap = new HashMap<>();
                groupMap.put(group.getGroupId(), group);
            }
        }
        if (customerFile.getTag() != null && !customerFile.getTag().trim().isEmpty()) {
            Set<String> tagCodes = Stream.of(customerFile.getTag().split(","))
                    .map(String::trim)
                    .filter(code -> !code.isEmpty())
                    .collect(Collectors.toSet());
            if (!tagCodes.isEmpty()) {
                List<CustomerTag> tags = customerTagMapper.findByCodeListAndType(tagCodes, 2);
                if (!tags.isEmpty()) {
                    tagMap = tags.stream()
                            .collect(Collectors.toMap(CustomerTag::getTagCode, tag -> tag));
                }
            }
        }

        CustomerFileResp resp = CustomerFileRespHelper.convert2CustomerFileResp(customerFile, groupMap, tagMap);
        log.info("CustomerFileServiceImpl.createCustomerFile END ==> {}", resp);
        return resp;
    }

    /**
     * 更新客户材料
     *
     * @param request 更新客户材料请求
     * @return 客户材料信息
     */
    public CustomerFileResp updateCustomerFile(UpdateCustomerFileRequest request) {
        log.info("CustomerFileServiceImpl.updateCustomerFile BEGIN ==> id: {}", request.getId());

        // 查询客户材料是否存在
        Long id = Long.parseLong(request.getId());
        CustomerFile customerFile = customerFileMapper.findById(id);
        if (customerFile == null) {
            throw new BusinessException(ErrorEnum.DATABASE_ERROR.getCode(), "客户材料不存在");
        }

        // 验证客户是否存在
        if (customerInfoMapper.findByCustomerId(request.getCustomerId()) == null) {
            throw new BusinessException(ErrorEnum.CUSTOMER_NOT_FOUND);
        }

        // 确定更新后的customerId和fileKey
        String newCustomerId = request.getCustomerId();
        String newFileKey = request.getFileKey() != null ? request.getFileKey() : customerFile.getFileKey();

        // 检查唯一键约束：如果customerId或fileKey发生变化，需要检查更新后的组合是否已存在（排除当前记录）
        if (!newCustomerId.equals(customerFile.getCustomerId()) || !newFileKey.equals(customerFile.getFileKey())) {
            CustomerFile existFile = customerFileMapper.findByCustomerIdAndFileKeyExcludeId(newCustomerId, newFileKey, id);
            if (existFile != null) {
                throw new BusinessException(ErrorEnum.DATABASE_ERROR.getCode(), "该客户下已存在相同的文件key");
            }
        }

        // 校验分组是否存在且type=2（客户材料分组）（如果传入了分组）
        if (request.getGroupCode() != null && !request.getGroupCode().trim().isEmpty()) {
            CustomerGroupInfo group = customerGroupMapper.findByGroupIdAndType(request.getGroupCode(), 2);
            if (group == null) {
                throw new BusinessException(ErrorEnum.GROUP_NOT_FOUND);
            }
        }

        // 处理标签字段
        // 如果tag为null，不更新tag字段（保持原值）
        // 如果tag为空数组，将tag设置为null
        // 如果tag有值，校验并规范化后设置
        if (request.getTag() != null) {
            if (request.getTag().isEmpty()) {
                // 空数组表示需要清空tag字段
                customerFile.setTag("");
            } else {
                // 有值则校验并规范化
                String normalizedTag = validateAndNormalizeTag(request.getTag());
                customerFile.setTag(normalizedTag);
            }
        }

        // 更新客户材料信息
        if (request.getFileKey() != null) {
            customerFile.setFileKey(request.getFileKey());
        }
        if (request.getFileName() != null) {
            customerFile.setFileName(request.getFileName());
        }
        if (request.getFileType() != null) {
            customerFile.setFileType(request.getFileType());
        }
        if (request.getSignAt() != null) {
            customerFile.setSignAt(request.getSignAt());
        }
        if (request.getExpireAt() != null) {
            customerFile.setExpireAt(request.getExpireAt());
        }
        customerFile.setCustomerId(request.getCustomerId());
        if (request.getGroupCode() != null) {
            customerFile.setGroupCode(request.getGroupCode());
        }
        EntityUtil.setModifyInfo(customerFile, UserContextHolder.getCurrentUserName());

        // 更新数据库
        int result = customerFileMapper.updateById(customerFile);
        if (result <= 0) {
            throw new BusinessException(ErrorEnum.DATABASE_ERROR);
        }

        // 查询分组和标签信息
        Map<String, CustomerGroupInfo> groupMap = null;
        Map<String, CustomerTag> tagMap = null;
        if (customerFile.getGroupCode() != null && !customerFile.getGroupCode().trim().isEmpty()) {
            CustomerGroupInfo group = customerGroupMapper.findByGroupIdAndType(customerFile.getGroupCode(), 2);
            if (group != null) {
                groupMap = new HashMap<>();
                groupMap.put(group.getGroupId(), group);
            }
        }
        if (customerFile.getTag() != null && !customerFile.getTag().trim().isEmpty()) {
            Set<String> tagCodes = Stream.of(customerFile.getTag().split(","))
                    .map(String::trim)
                    .filter(code -> !code.isEmpty())
                    .collect(Collectors.toSet());
            if (!tagCodes.isEmpty()) {
                List<CustomerTag> tags = customerTagMapper.findByCodeListAndType(tagCodes, 2);
                if (!tags.isEmpty()) {
                    tagMap = tags.stream()
                            .collect(Collectors.toMap(CustomerTag::getTagCode, tag -> tag));
                }
            }
        }

        CustomerFileResp resp = CustomerFileRespHelper.convert2CustomerFileResp(customerFile, groupMap, tagMap);
        log.info("CustomerFileServiceImpl.updateCustomerFile END ==> {}", resp);
        return resp;
    }

    /**
     * 删除客户材料
     *
     * @param request 删除客户材料请求
     * @return 删除结果
     */
    public boolean deleteCustomerFile(DeleteCustomerFileRequest request) {
        log.info("CustomerFileServiceImpl.deleteCustomerFile BEGIN ==> id: {}", request.getId());

        // 查询客户材料是否存在
        Long recordId = Long.parseLong(request.getId());
        CustomerFile customerFile = customerFileMapper.findById(recordId);
        if (customerFile == null) {
            throw new BusinessException(ErrorEnum.DATABASE_ERROR.getCode(), "客户材料不存在");
        }

        // 设置ukid为记录主键id
        customerFile.setUkid(recordId);
        EntityUtil.setModifyInfo(customerFile, UserContextHolder.getCurrentUserName());

        // 更新数据库
        int result = customerFileMapper.updateById(customerFile);
        if (result <= 0) {
            throw new BusinessException(ErrorEnum.DATABASE_ERROR);
        }

        log.info("CustomerFileServiceImpl.deleteCustomerFile END ==> id: {}", request.getId());
        return true;
    }

    /**
     * 根据客户ID查询客户材料列表（树状结构）
     *
     * @param request 查询客户材料列表请求
     * @return 客户材料树状结构
     */
    public CustomerFileTreeResp queryFileListByCustomerId(QueryCustomerFileListByCustomerIdRequest request) {
        // 校验客户是否存在
        CustomerInfo customerInfo = customerInfoMapper.findByCustomerId(request.getCustomerId());
        if (customerInfo == null) {
            throw new BusinessException(ErrorEnum.CUSTOMER_NOT_FOUND);
        }

        // 查询该客户的所有材料（不分页）
        List<CustomerFile> allFiles = customerFileMapper.selectByCustomerId(request.getCustomerId());

        // 查询所有客户材料分组（type=2）
        List<CustomerGroupInfo> allGroups = customerGroupMapper.selectByType(2);

        // 构建分组映射（groupId -> CustomerGroupInfo）
        Map<String, CustomerGroupInfo> groupMap = allGroups.stream()
                .collect(Collectors.toMap(CustomerGroupInfo::getGroupId, g -> g));

        // 查询所有标签信息（type=2，客户材料标签）
        List<CustomerTag> allTags = customerTagMapper.selectByType(2);
        Map<String, CustomerTag> tagMap = allTags.stream()
                .collect(Collectors.toMap(CustomerTag::getTagCode, tag -> tag));

        // 按分组code分组文件（groupCode -> List<CustomerFile>）
        Map<String, List<CustomerFile>> filesByGroup = allFiles.stream()
                .filter(f -> f.getGroupCode() != null && !f.getGroupCode().trim().isEmpty())
                .collect(Collectors.groupingBy(CustomerFile::getGroupCode));

        // 构建分组层级结构
        List<CustomerFileGroupResp> groupList = buildGroupHierarchy(filesByGroup, groupMap, tagMap);

        // 添加未分组的文件
        List<CustomerFile> ungroupedFiles = allFiles.stream()
                .filter(f -> f.getGroupCode() == null || f.getGroupCode().trim().isEmpty())
                .collect(Collectors.toList());
        if (!ungroupedFiles.isEmpty()) {
            CustomerFileGroupResp ungroupedGroup = new CustomerFileGroupResp();
            ungroupedGroup.setGroupCode(null);
            ungroupedGroup.setGroupName("未分组");
            ungroupedGroup.setParentGroupCode(null);
            ungroupedGroup.setFileList(ungroupedFiles.stream()
                    .map(file -> CustomerFileRespHelper.convert2CustomerFileResp(file, groupMap, tagMap))
                    .collect(Collectors.toList()));
            ungroupedGroup.setChildren(new ArrayList<>());
            groupList.add(ungroupedGroup);
        }

        CustomerFileTreeResp response = new CustomerFileTreeResp();
        response.setGroupList(groupList);
        return response;
    }

    /**
     * 查询客户材料列表（分页，平铺展示）
     *
     * @param request 查询客户材料列表请求
     * @return 客户材料列表
     */
    public CustomerFileListResp queryFileList(QueryCustomerFileListRequest request) {
        // 创建分页对象
        Page<CustomerFile> page = new Page<>(request.getPageNum(), request.getPageSize());

        // 分页查询客户材料列表
        IPage<CustomerFile> filePage = customerFileMapper.selectFileListPage(
                page,
                request.getCustomerId(),
                request.getGroupCode(),
                request.getTagCode());

        // 批量查询分组和标签信息
        Set<String> groupCodes = filePage.getRecords().stream()
                .map(CustomerFile::getGroupCode)
                .filter(code -> code != null && !code.trim().isEmpty())
                .collect(Collectors.toSet());
        final Map<String, CustomerGroupInfo> groupMap;
        if (!groupCodes.isEmpty()) {
            List<CustomerGroupInfo> groups = customerGroupMapper.selectByType(2);
            groupMap = groups.stream()
                    .filter(g -> groupCodes.contains(g.getGroupId()))
                    .collect(Collectors.toMap(CustomerGroupInfo::getGroupId, g -> g));
        } else {
            groupMap = new HashMap<>();
        }

        Set<String> tagCodes = filePage.getRecords().stream()
                .map(CustomerFile::getTag)
                .filter(tag -> tag != null && !tag.trim().isEmpty())
                .flatMap(tag -> Stream.of(tag.split(",")))
                .map(String::trim)
                .filter(code -> !code.isEmpty())
                .collect(Collectors.toSet());
        final Map<String, CustomerTag> tagMap;
        if (!tagCodes.isEmpty()) {
            List<CustomerTag> tags = customerTagMapper.findByCodeListAndType(tagCodes, 2);
            tagMap = tags.stream()
                    .collect(Collectors.toMap(CustomerTag::getTagCode, tag -> tag));
        } else {
            tagMap = new HashMap<>();
        }

        // 转换为响应对象（平铺展示）
        List<CustomerFileResp> fileList = filePage.getRecords().stream()
                .map(file -> CustomerFileRespHelper.convert2CustomerFileResp(file, groupMap, tagMap))
                .collect(Collectors.toList());

        CustomerFileListResp response = new CustomerFileListResp();
        response.setFileList(fileList);
        response.setTotal(filePage.getTotal());
        response.setPageNum(request.getPageNum());
        response.setPageSize(request.getPageSize());
        response.setTotalPages((int) filePage.getPages());

        return response;
    }

    /**
     * 构建分组层级结构
     *
     * @param filesByGroup 按分组code分组的文件
     * @param groupMap 分组映射
     * @param tagMap 标签映射
     * @return 分组层级列表
     */
    private List<CustomerFileGroupResp> buildGroupHierarchy(Map<String, List<CustomerFile>> filesByGroup,
                                                             Map<String, CustomerGroupInfo> groupMap,
                                                             Map<String, CustomerTag> tagMap) {
        if (CollectionUtils.isEmpty(filesByGroup)) {
            return new ArrayList<>();
        }

        // 构建分组响应对象
        Map<String, CustomerFileGroupResp> groupRespMap = new HashMap<>();
        for (Map.Entry<String, List<CustomerFile>> entry : filesByGroup.entrySet()) {
            String groupCode = entry.getKey();
            List<CustomerFile> files = entry.getValue();

            CustomerGroupInfo group = groupMap.get(groupCode);
            if (group == null) {
                continue;
            }

            CustomerFileGroupResp groupResp = new CustomerFileGroupResp();
            groupResp.setGroupCode(groupCode);
            groupResp.setGroupName(group.getGroupName());
            groupResp.setParentGroupCode(group.getParentGroupId());
            groupResp.setFileList(files.stream()
                    .map(file -> CustomerFileRespHelper.convert2CustomerFileResp(file, groupMap, tagMap))
                    .collect(Collectors.toList()));
            groupResp.setChildren(new ArrayList<>());
            groupRespMap.put(groupCode, groupResp);
        }

        // 构建层级关系
        List<CustomerFileGroupResp> rootGroups = new ArrayList<>();
        for (CustomerFileGroupResp groupResp : groupRespMap.values()) {
            String parentGroupCode = groupResp.getParentGroupCode();
            if (parentGroupCode == null || parentGroupCode.trim().isEmpty() || !groupRespMap.containsKey(parentGroupCode)) {
                // 根节点
                rootGroups.add(groupResp);
            } else {
                // 子节点
                CustomerFileGroupResp parent = groupRespMap.get(parentGroupCode);
                if (parent != null) {
                    parent.getChildren().add(groupResp);
                }
            }
        }

        // 递归排序子节点
        for (CustomerFileGroupResp rootGroup : rootGroups) {
            sortGroupChildren(rootGroup);
        }

        return rootGroups;
    }

    /**
     * 递归排序分组子节点
     *
     * @param group 分组
     */
    private void sortGroupChildren(CustomerFileGroupResp group) {
        if (!CollectionUtils.isEmpty(group.getChildren())) {
            group.getChildren().sort(Comparator.comparing(CustomerFileGroupResp::getGroupName));
            for (CustomerFileGroupResp child : group.getChildren()) {
                sortGroupChildren(child);
            }
        }
    }

    /**
     * 规范化并校验标签：
     * 1) trim去空白；2) 过滤空值；3) 去重；4) 校验每个tag_code长度不超过32；5) 校验每个tag_code在customer_tag表中存在且type=2（客户材料标签）
     *
     * @param tagList 标签列表（每个tag_code对应customer_tag表的tag_code字段，type必须为2）
     * @return 规范化后的标签编码字符串（逗号分隔）
     */
    private String validateAndNormalizeTag(List<String> tagList) {
        if (tagList == null || tagList.isEmpty()) {
            return null;
        }

        // trim去空白并过滤空值
        List<String> normalizedTags = new ArrayList<>();
        for (String tagCode : tagList) {
            if (tagCode != null) {
                String trimmed = tagCode.trim();
                if (!trimmed.isEmpty()) {
                    // 校验单个tag_code长度不超过32
                    if (trimmed.length() > 32) {
                        throw new BusinessException(ErrorEnum.DATABASE_ERROR.getCode(), "标签编码长度不能超过32");
                    }
                    normalizedTags.add(trimmed);
                }
            }
        }

        if (normalizedTags.isEmpty()) {
            return null;
        }

        // 去重校验
        Set<String> tagsSet = new HashSet<>(normalizedTags);
        if (tagsSet.size() != normalizedTags.size()) {
            throw new BusinessException(ErrorEnum.TAG_REPEAT);
        }

        // 校验标签存在且type=2（客户材料标签）
        List<CustomerTag> result = customerTagMapper.findByCodeListAndType(tagsSet, 2);
        if (result.size() != tagsSet.size()) {
            throw new BusinessException(ErrorEnum.TAG_NOT_FOUND);
        }

        return String.join(",", normalizedTags);
    }

}

